package com.hup.minicontroller.client.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;

import androidx.annotation.Nullable;

import com.hup.minicontroller.client.R;
import com.hup.minicontroller.common.model.dto.TouchPadTouchRequest;

import lombok.Setter;

/**
 * 触控板view
 *
 * @author hugan
 * @date 2021/5/6
 */
public class TouchPadView extends FrameLayout {
    private static final String TAG = TouchPadView.class.getSimpleName();
    private static final int LAYOUT_ID = R.layout.touch_pad_view;

    @Setter
    private TouchEventCallback touchEventCallback;

    public TouchPadView(Context context) {
        this(context, null);
    }

    public TouchPadView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TouchPadView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public TouchPadView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context, attrs);
    }

    @SuppressWarnings("unused")
    private void init(Context context, AttributeSet attrs) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(LAYOUT_ID, this);
        setOnTouchListener(new MyTouchListener());
    }

    private class MyTouchListener implements OnTouchListener {
        /**
         * 单击(快速按下,无移动,快速抬起)的抬起时,n毫秒内无按下事件,才确定触发单击事件;
         * 注意!!!!!!这个值太大,会导致点击事件延迟过大,本类的几个时间值,都没长期测试,实际时是需要多次调整和体验后确定值的
         */
        private static final int CLICK_DELAY = 210;
        private int lastX, lastY;

        /**
         * 按下时的状态
         */
        private int x0, y0;
        private long lastDownTime = 0;
        /**
         * 按下后,有没有长距离移动
         */
        private boolean hadMoveLong;
        private boolean dragging;

        private Runnable runnableClick = () -> {
            long cur = System.currentTimeMillis();
            if (!dragging && cur - lastDownTime > CLICK_DELAY) {
                Log.i(TAG, "确认发送点击事件: ");
                onClick();
            } else {
                Log.i(TAG, "取消点击事件: ");
            }
        };

        @Override
        @SuppressLint("ClickableViewAccessibility")
        public boolean onTouch(View v, MotionEvent e) {
            if (touchEventCallback == null) return true;
            int x = (int) e.getX();
            int y = (int) e.getY();
            long t = e.getEventTime();
            switch (e.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    /*
                    快速双击按下:上次按下后没长距离移动,且距离上次按下时间<span
                    操作:按下(并拖拽)事件
                     */
                    boolean fastDoublePress = !hadMoveLong && t - lastDownTime < 200;
                    x0 = x;
                    y0 = y;
                    dragging = false;
                    lastDownTime = t;
                    hadMoveLong = false;
                    if (!fastDoublePress) {
                        onMoveStart();
                    } else {
                        dragging = true;
                        onPress();
                    }
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (Math.abs(lastX - x) < 1 && Math.abs(lastY - y) < 1) return true;//过滤微小移动
                    onMove(x, y);
                    if (Math.abs(lastX - x) < 10 && Math.abs(lastY - y) < 10) hadMoveLong = true;
                    break;
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
                    /*
                    快速点击:按下后没长距离移动,且距离上次按下时间<span
                     */
                    if (!dragging) {
                        boolean isFastClick = !hadMoveLong && t - lastDownTime < 150;
                        if (isFastClick) {
                            postDelayed(runnableClick, CLICK_DELAY);
                        } else {
                            onMoveStop();
                        }
                    } else {
                        onUp();
                    }
                    break;
            }
            lastX = x;
            lastY = y;
            return true;
        }

        private void onMoveStart() {
            touchEventCallback.handleEvent(new TouchPadTouchRequest(TouchPadTouchRequest.ACTION_MOVE_START, 0, 0));
        }

        private void onMove(int x, int y) {
            touchEventCallback.handleEvent(new TouchPadTouchRequest(TouchPadTouchRequest.ACTION_MOVE, x - x0, y - y0));
        }

        private void onMoveStop() {
            touchEventCallback.handleEvent(new TouchPadTouchRequest(TouchPadTouchRequest.ACTION_MOVE_STOP, 0, 0));
        }

        private void onPress() {
            touchEventCallback.handleEvent(new TouchPadTouchRequest(TouchPadTouchRequest.ACTION_PRESS, 0, 0));
        }

        private void onUp() {
            touchEventCallback.handleEvent(new TouchPadTouchRequest(TouchPadTouchRequest.ACTION_UP, 0, 0));
        }

        private void onClick() {
            touchEventCallback.handleEvent(new TouchPadTouchRequest(TouchPadTouchRequest.ACTION_CLICK, 0, 0));
        }
    }

    /**
     * 触摸事件回调
     */
    public interface TouchEventCallback {
        void handleEvent(TouchPadTouchRequest touchPadTouch);
    }

}
